//ref link : http://www.cplusplus.com/reference/list/list/
//ref link ：https://blog.csdn.net/lym940928/article/details/83063699
#include<iostream>
#include<list>

/*
Declare:
template < class T, class Alloc = allocator<T> > class list;

Member functions:
(constructor)
    Construct list (public member function )

(destructor)
    List destructor (public member function )

operator=
    Assign content (public member function )

Iterators:

begin
    Return iterator to beginning (public member function )

end
    Return iterator to end (public member function )

rbegin
    Return reverse iterator to reverse beginning (public member function )

rend
    Return reverse iterator to reverse end (public member function )

cbegin
    Return const_iterator to beginning (public member function )

cend
    Return const_iterator to end (public member function )

crbegin
    Return const_reverse_iterator to reverse beginning (public member function )

crend
    Return const_reverse_iterator to reverse end (public member function )

Capacity:

empty
    Test whether container is empty (public member function )

size
    Return size (public member function )

max_size
    Return maximum size (public member function )

Element access:

front
    Access first element (public member function )

back
    Access last element (public member function )

Modifiers:

assign
    Assign new content to container (public member function )

emplace_front
    Construct and insert element at beginning (public member function )

push_front
    Insert element at beginning (public member function )

pop_front
    Delete first element (public member function )

emplace_back
    Construct and insert element at the end (public member function )

push_back
    Add element at the end (public member function )

pop_back
    Delete last element (public member function )

emplace
    Construct and insert element (public member function )

insert
    Insert elements (public member function )

erase
    Erase elements (public member function )

swap
    Swap content (public member function )

resize
    Change size (public member function )

clear
    Clear content (public member function )

Operations:

splice
    Transfer elements from list to list (public member function )

remove
    Remove elements with specific value (public member function )

remove_if
    Remove elements fulfilling condition (public member function template )

unique
    Remove duplicate values (public member function )

merge
    Merge sorted lists (public member function )

sort
    Sort elements in container (public member function )

reverse
    Reverse the order of elements (public member function )

Observers:

get_allocator
    Get allocator (public member function )

Non-member function overloads

relational operators (list)
    Relational operators for list (function )

swap (list)
    Exchanges the contents of two lists (function template )

*/

void useContructer()
{
    // constructors used in the same order as described above:
    std::list<int> first;                                // empty list of ints
    std::list<int> second (4,100);                       // four ints with value 100
    std::list<int> third (second.begin(),second.end());  // iterating through second
    std::list<int> fourth (third);                       // a copy of third

    // the iterator constructor can also be used to construct from arrays:
    int myints[] = {16,2,77,29};
    std::list<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );

    std::cout << "The contents of fifth are: ";
    for (std::list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)
        std::cout << *it << ' ';

    std::cout << '\n';
}

void useOperator()
{
    std::list<int> first (3);      // list of 3 zero-initialized ints
    std::list<int> second (5);     // list of 5 zero-initialized ints

    second = first;
    first = std::list<int>();

    std::cout << "Size of first: " << int (first.size()) << '\n';
    std::cout << "Size of second: " << int (second.size()) << '\n';
}

void useIterator()
{
    int myints[] = {75,23,65,42,13};
    std::list<int> mylist (myints,myints+5);

    std::cout << "mylist contains:";
    for (std::list<int>::iterator it=mylist.begin(); it != mylist.end(); ++it)
        std::cout << ' ' << *it;

    std::cout << '\n';
}

void use_empty()
{
    std::list<int> mylist;
    int sum (0);

    for (int i=1;i<=10;++i) mylist.push_back(i);

    while (!mylist.empty())
    {
        sum += mylist.front();
        mylist.pop_front();
    }

    std::cout << "total: " << sum << '\n';
}

void use_size()
{
    std::list<int> myints;
    std::cout << "0. size: " << myints.size() << '\n';

    for (int i=0; i<10; i++) myints.push_back(i);
    std::cout << "1. size: " << myints.size() << '\n';

    myints.insert (myints.begin(),10,100);
    std::cout << "2. size: " << myints.size() << '\n';

    myints.pop_back();
    std::cout << "3. size: " << myints.size() << '\n';
}

void use_max_size()
{
    unsigned int i;
    std::list<int> mylist;

    std::cout << "Enter number of elements: 10";
    //std::cin >> i;
    i = 10;
    if (i<mylist.max_size()) mylist.resize(i);
    else std::cout << "That size exceeds the limit.\n";
}

void useElementAccess()
{
    std::list<int> mylist;

    mylist.push_back(77);
    mylist.push_back(22);

    // now front equals 77, and back 22

    mylist.front() -= mylist.back();

    std::cout << "mylist.front() is now " << mylist.front() << '\n';
}

void use_assign()
{
    std::list<int> first;
    std::list<int> second;

    first.assign (7,100);                      // 7 ints with value 100

    second.assign (first.begin(),first.end()); // a copy of first

    int myints[]={1776,7,4};
    first.assign (myints,myints+3);            // assigning from array

    std::cout << "Size of first: " << int (first.size()) << '\n';
    std::cout << "Size of second: " << int (second.size()) << '\n';
}

void use_splice()
{
    std::list<int> mylist1, mylist2;
    std::list<int>::iterator it;

    // set some initial values:
    for (int i=1; i<=4; ++i)
        mylist1.push_back(i);      // mylist1: 1 2 3 4

    for (int i=1; i<=3; ++i)
        mylist2.push_back(i*10);   // mylist2: 10 20 30

    it = mylist1.begin();
    ++it;                         // points to 2

    mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                    // mylist2 (empty)
                                    // "it" still points to 2 (the 5th element)
                                            
    mylist2.splice (mylist2.begin(),mylist1, it);
                                    // mylist1: 1 10 20 30 3 4
                                    // mylist2: 2
                                    // "it" is now invalid.
    it = mylist1.begin();
    std::advance(it,3);           // "it" points now to 30

    mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
                                    // mylist1: 30 3 4 1 10 20

    std::cout << "mylist1 contains:";
    for (it=mylist1.begin(); it!=mylist1.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    std::cout << "mylist2 contains:";
    for (it=mylist2.begin(); it!=mylist2.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';
}

int main()
{
    useContructer();
    useOperator();
    useIterator();
    //useCapacity
    use_empty();
    use_size();
    use_max_size();
    //useElementAccess
    useElementAccess();
    //useModifiers
    use_assign();
    //useOperations
    use_splice();


    return 0;
}